﻿using System;
using System.Web.Mvc;

using MSAcademic.v2.Infrastructure.Login;
using MSAcademic.v2.Infrastructure.PasswordRecovery;
using MSAcademic.v2.Infrastructure.User;
using MSAcademic.v2.Web.Areas.Admin.Models.Login;

using Postal;

namespace MSAcademic.v2.Web.Areas.Admin.Controllers
{
    public partial class LoginController : Controller
    {
        public ActionResult Registration(string regToken)
        {
            var model = _registrationModelFactory();
            if (string.IsNullOrEmpty(regToken) || model.User != null)
            {
                return RedirectToRoute("Index");
            }

            model.RegToken = regToken;
            if (!model.IsTokenValid)
            {
                return RedirectToRoute("Index");
            }

            ViewData["currentView"] = "Login";  // Note: ViewData["currentView"] = "Login" forces a different (narrower) UI
            return View(model);
        }
        [HttpPost, ValidateAntiForgeryToken]
        public ActionResult Registration(RegistrationModel model)
        {
            ViewData["currentView"] = "Login";  // Note: ViewData["currentView"] = "Login" forces a different (narrower) UI

            if (!ModelState.IsValid) { return View(model); }

            _userCommands.SaveNew(model.Username, model.Password, model.Email, model.RegToken);
            _loginService.SignIn(model.Username, false);

            model.ActingRole = _userQueries.TryGetWhereUsername(model.Username).ActingRole;
            model.IsFormSuccess = true;
            return View(model);
        }

        public ActionResult SignIn(string returnUrl)
        {
            var model = _signInModelFactory();
            if (model.User != null)
            {
                if (!string.IsNullOrWhiteSpace(returnUrl)) { return Redirect(returnUrl); }
                return RedirectToRoute("AdminHome");
            }

            ViewData["currentView"] = "Login";
            return View(model);
        }
        [HttpPost, ValidateAntiForgeryToken]
        public ActionResult SignIn(SignInModel model, string returnUrl)
        {
            ViewData["currentView"] = "Login";

            if (!ModelState.IsValid) { return View(model); }

            var isAuthenticated = _userQueries.TryGetWhereUsernameAndPassword(model.Username, model.Password) != null;
            if (!isAuthenticated)
            {
                model.HasAuthenticationErrors = true;
                model.Password = string.Empty;
                
                return View(model);
            }
            _loginService.SignIn(model.Username, model.IsLongSession);

            return
                (!string.IsNullOrWhiteSpace(returnUrl))
                    ? (ActionResult)Redirect(returnUrl)
                    : RedirectToRoute("AdminHome");
        }


        public ActionResult SignOut(string returnUrl)
        {
            _loginService.SignOut();
            return
                (!string.IsNullOrWhiteSpace(returnUrl))
                    ? (ActionResult)Redirect(returnUrl)
                    : RedirectToRoute("AdminSignIn");
        }

        public ActionResult RequestPasswordReset()
        {
            var model = _requestPasswordResetModelFactory();

            ViewData["currentView"] = "Login";
            return View(model);
        }
        [HttpPost, ValidateAntiForgeryToken]
        public ActionResult RequestPasswordReset(RequestPasswordResetModel model)
        {
            if (!ModelState.IsValid) { return View(model); }

            var recoveryToken = _passwordRecoveryService.GenerateToken(model.Username);

            dynamic email = new Email("ResetPasswordToken");
            email.To = model.User.Email;
            email.Token = recoveryToken;
            email.Username = model.Username;
            email.ResetPasswordUrl = Url.RouteUrl("AdminResetPassword", new { tokenValue = recoveryToken }, Request.Url.Scheme);
            email.Send();
            //TODO: prominit ovo da salje prave mailove prije deploya
            model.IsFormSuccess = true;

            ViewData["currentView"] = "Login";
            return View(model);
        }

        public ActionResult ResetPassword(string tokenValue)
        {
            if (string.IsNullOrWhiteSpace(tokenValue))
            {
                return RedirectToRoute("AdminSignIn");
            }

            var model = _resetPasswordModelFactory();
            model.TokenValue = tokenValue;

            ViewData["currentView"] = "Login";            
            return View(model);
        }
        [HttpPost, ValidateAntiForgeryToken]
        public ActionResult ResetPassword(ResetPasswordModel model)
        {
            if (!ModelState.IsValid) { return View(model); }

            if (model.IsUserSignedIn)
            {
                _loginService.SignOut();
            }
            _userCommands.ChangePassword(model.UserId, model.NewPassword);
            _passwordRecoveryService.MarkTokenAsUsed(model.TokenValue);

            model.IsFormSuccess = true;

            ViewData["currentView"] = "Login";
            return View(model);
        }
    }

    public partial class LoginController
    {
        private readonly ILoginService _loginService;
        private readonly IUserQueries _userQueries;
        private readonly IUserCommands _userCommands;
        private readonly IPasswordRecoveryService _passwordRecoveryService;
        private readonly Func<RegistrationModel> _registrationModelFactory;
        private readonly Func<SignInModel> _signInModelFactory;
        private readonly Func<RequestPasswordResetModel> _requestPasswordResetModelFactory;
        private readonly Func<ResetPasswordModel> _resetPasswordModelFactory;

        public LoginController(
            ILoginService loginService,
            IUserQueries userQueries,
            IUserCommands userCommands,
            IPasswordRecoveryService passwordRecoveryService,

            Func<RegistrationModel> registrationModelFactory,
            Func<SignInModel> signInModelFactory,
            Func<RequestPasswordResetModel> requestPasswordResetModelFactory,
            Func<ResetPasswordModel> resetPasswordModelFactory)
        {
            _loginService = loginService;
            _userQueries = userQueries;
            _userCommands = userCommands;
            _passwordRecoveryService = passwordRecoveryService;
            _registrationModelFactory = registrationModelFactory;
            _signInModelFactory = signInModelFactory;
            _requestPasswordResetModelFactory = requestPasswordResetModelFactory;
            _resetPasswordModelFactory = resetPasswordModelFactory;
        }
    }
}
